package multi_thread.advanced.concurrent_collection;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Cheng Jun
 * Description: ConcurrentHashMap 学习，数组+链表+红黑树
 * 新增元素时，如果在数组同一个位置发生并发冲突的话，就采用CAS进行设置，设置成功的元素作为对象锁，
 * 未设置成功的元素获取对象锁，然后设置尾节点（1.8尾插法）
 * @version 1.0
 * @date 2021/10/9 22:01
 * @see ConcurrentHashMap
 * 重点掌握
 */
public class ConcurrentHashMapExample {

    public static void main(String[] args) throws InterruptedException {

        ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();
        // Neither the key nor the value can be null.
        // 所有的并发集合都允许 null值，因为null 会有歧义。比如 非并发环境下 hashmap.get(key) 得到null，你并不知道map中到底有没有key，
        // 这时，你要用 hashmap.contains(key) 判断，但是在并发环境，如果并发集合允许null的话，你先get得到null，再用contains判断其实没有意义。
        // 因为在你 get 和 contains的间隙中，可能key被放进去了。
        // concurrentHashMap.put("name", null);
        // System.out.println(concurrentHashMap.get("name"));
        comparePerformance();
    }

    static void comparePerformance() {
        // 使用 Hashtable put 100_000 个数据，使用ConcurrentHashMap put 100_000 个数据 比较效率
        // Hashtable<String, Integer> map = new Hashtable<>();
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                long start = System.currentTimeMillis();
                for (int j = 0; j < 100_000; j++) {
                    map.put("a" + j, j);
                }
                System.out.println(System.currentTimeMillis() - start);
            });
            thread.start();
        }
    }

}
